﻿using System.Collections.Generic;
using System.Linq.Dynamic.Core;
using System.Reflection;
using System.Text;
using SqlSugar;

namespace Common
{
    public static class SqlSugarExt
    {
        /// <summary>
        /// 根据条件对象查询数据
        /// </summary>
        /// <typeparam name="T">表实体对象</typeparam>
        /// <param name="sugarQueryable">sugar查询对象</param>
        /// <param name="whereObj">查询实体</param>
        /// <returns></returns>
        public static ISugarQueryable<T> Where<T>(this ISugarQueryable<T> sugarQueryable, object whereObj)
        {
            var sugarQueryableWhere = sugarQueryable;

            var whereObjType = whereObj.GetType();
            var whereDic = new Dictionary<string, object>();      //装载where条件
            var inDic = new Dictionary<string,List<int>>();       //装载in条件

            foreach (var property in whereObjType.GetProperties())
            {
                var curName = property.Name;
                if (property.PropertyType.Name.Equals("List`1"))  //集合
                {
                    var curValue = property.GetValue(whereObj, null);
                    inDic.Add(curName, (List<int>)curValue);
                }
                else
                {
                    var curValue = property.GetValue(whereObj, null);
                    if (curValue==null) continue;                //排除参数值为null的查询条件
                    whereDic.Add(curName.ToLower(), curValue);
                }
            }

            var dbModelType = typeof(T);

            var expSb = new StringBuilder();

            foreach (var property in dbModelType.GetProperties())      //遍历dbModel属性
            {
                foreach (var (key, value) in whereDic)                     
                {
                    if (property.Name.ToLower() != key) continue;

                    expSb.Append(ProcessExp(property,value));          //拼接where条件
                    expSb.Append(" and ");
                }
            }

            if (expSb.Length != 0)                                     //转换where条件表达式树
            {
                var exp = expSb.ToString().Remove(expSb.Length - 4, 4);
                //var e = System.Linq.DynamicCore.DynamicExpression.ParseLambda<T, bool>(exp);
                var e = DynamicExpressionParser.ParseLambda<T, bool>(ParsingConfig.Default, false, exp);

                sugarQueryableWhere = sugarQueryable.Where(e);
            }


            if (inDic.Count == 0) return sugarQueryableWhere;

            foreach (var (key, value) in inDic)                       //转换in条件表达式树
            {
                //var e2 = System.Linq.DynamicCore.DynamicExpression.ParseLambda<T, object>(key);
                var e2 = DynamicExpressionParser.ParseLambda<T, object>(ParsingConfig.Default, false, key);
                sugarQueryableWhere = sugarQueryableWhere.In(e2, value);
            }

            return sugarQueryableWhere;
        }

        /// <summary>
        /// 处理表达式树拼接
        /// </summary>
        /// <param name="property"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private static string ProcessExp(PropertyInfo property,object value)
        {
           
            //引用类型 此处只考虑string类型的情况
            if (!property.PropertyType.IsValueType) return $"{property.Name} = \"{value}\" ";

            //可空值类型 此处只考虑简单值类型
            if (property.PropertyType.Name.Equals("Nullable`1"))   
            {
                if (property.PropertyType.GenericTypeArguments[0].Name.Equals("DateTime"))
                {
                    return $"{property.Name} = Convert.ToDateTime(\"{value}\") ";
                }
                    
                return $"{property.Name} = {value} ";
            }

            //值类型  此处只考虑简单值类型
            if (property.PropertyType.Name.Equals("DateTime"))  
            {
                return $"{property.Name} = Convert.ToDateTime(\"{value}\") ";
            }

            return $"{property.Name} = {value} ";

            
        }

       
        
    }
}